<template>
  <div class="code-editor-container">
    <div class="editor-panes" ref="editorContainer">
      <div class="editor-pane html-pane">
        <div class="pane-header">HTML</div>
        <div class="editor-content">
          <Codemirror
            v-model="htmlCode"
            :extensions="htmlExtensions"
            :theme="editorTheme"
            @change="updatePreview"
          />
        </div>
      </div>
      <div class="editor-pane css-pane">
        <div class="pane-header">CSS</div>
        <div class="editor-content">
          <Codemirror
            v-model="cssCode"
            :extensions="cssExtensions"
            :theme="editorTheme"
            @change="updatePreview"
          />
        </div>
      </div>
      <div class="editor-pane js-pane">
        <div class="pane-header">JavaScript</div>
        <div class="editor-content">
          <Codemirror
            v-model="jsCode"
            :extensions="jsExtensions"
            :theme="editorTheme"
            @change="updatePreview"
          />
        </div>
      </div>
    </div>

    <div class="preview-pane">
      <div class="pane-header">预览</div>
      <iframe ref="previewFrame" class="preview-frame"></iframe>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, watch } from "vue";
import { Codemirror } from "vue-codemirror";
import { html } from "@codemirror/lang-html";
import { css } from "@codemirror/lang-css";
import { javascript } from "@codemirror/lang-javascript";
import { oneDark } from "@codemirror/theme-one-dark";
import Split from "split.js";

const props = defineProps({
  settings: {
    type: Object,
    default: () => ({
      theme: "dark",
      fontSize: 14,
      autoSave: true,
    }),
  },
});

const htmlCode = ref(`<div id="app">
  <h1>{{ message }}</h1>
  <div id="three-container"></div>
</div>`);

const cssCode = ref(`body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 20px;
}
#three-container {
  width: 100%;
  height: 300px;
}`);

const jsCode = ref(`// 使用全局THREE对象，而不是ES模块导入
// import * as THREE from 'three';

// Vue 3 的初始化方式
const { createApp, ref, onMounted } = Vue;

createApp({
  setup() {
    const message = ref('Hello from Vue!');
    
    onMounted(() => {
      // Three.js 初始化
      const scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      const renderer = new THREE.WebGLRenderer();
      
      const container = document.getElementById('three-container');
      renderer.setSize(container.clientWidth, 300);
      container.appendChild(renderer.domElement);
      
      const geometry = new THREE.BoxGeometry();
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
      const cube = new THREE.Mesh(geometry, material);
      scene.add(cube);
      
      camera.position.z = 5;
      
      function animate() {
        requestAnimationFrame(animate);
        
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        
        renderer.render(scene, camera);
      }
      
      animate();
    });
    
    return {
      message
    };
  }
}).mount('#app');`);

const previewFrame = ref(null);
const editorContainer = ref(null);

const htmlExtensions = [html()];
const cssExtensions = [css()];
const jsExtensions = [javascript()];
const editorTheme = oneDark;

function updatePreview() {
  const iframe = previewFrame.value;
  if (!iframe) return;

  const doc = iframe.contentDocument || iframe.contentWindow.document;
  doc.open();
  doc.write(`
    <!DOCTYPE html>
    <html>
      <head>
        <style>${cssCode.value}</style>
        <script src="https://unpkg.com/vue@3/dist/vue.global.js"><\/script>
        <script src="https://unpkg.com/three@0.160.0/build/three.min.js"><\/script>
      </head>
      <body>
        ${htmlCode.value}
        <script>
          ${jsCode.value}
        <\/script>
      </body>
    </html>
  `);
  doc.close();
}

onMounted(() => {
  // 初始化 Split.js 实现面板拖拽调整大小
  Split([".html-pane", ".css-pane", ".js-pane"], {
    direction: "horizontal",
    sizes: [33, 33, 34],
    minSize: 100,
    gutterSize: 5,
  });

  Split([".editor-panes", ".preview-pane"], {
    direction: "vertical",
    sizes: [60, 40],
    minSize: 100,
    gutterSize: 5,
  });

  // 初始预览
  updatePreview();
});

// 监听代码变化，更新预览
watch(
  [htmlCode, cssCode, jsCode],
  () => {
    updatePreview();
  },
  { deep: true }
);
</script>

<style scoped>
.code-editor-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100%;
  overflow: hidden;
}

.editor-panes {
  display: flex;
  flex: 1;
}

.editor-pane {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
  border-right: 1px solid #333;
}

.pane-header {
  padding: 8px 12px;
  background-color: #1e1e1e;
  color: #fff;
  font-weight: bold;
  border-bottom: 1px solid #333;
}

.editor-content {
  flex: 1;
  overflow: hidden;
}

.preview-pane {
  flex: 1;
  display: flex;
  flex-direction: column;
  background-color: #fff;
}

.preview-frame {
  flex: 1;
  width: 100%;
  border: none;
  background-color: white;
}

:deep(.cm-editor) {
  height: 100%;
  font-size: v-bind('props.settings.fontSize + "px"');
}

/* Split.js 样式 */
.gutter {
  background-color: #333;
  background-repeat: no-repeat;
  background-position: 50%;
}

.gutter.gutter-horizontal {
  cursor: col-resize;
}

.gutter.gutter-vertical {
  cursor: row-resize;
}
</style>
